<?php
include 'exception.php';
class SSKIOStreamException extends SSKCustomException{};
interface ISSKStream {
	public function Open($arg1, $arg2);
	public function Close();
	public function GetStream();
	public function GetFSize();
}
interface IStream extends ISSKStream {
	public function Read($arg1);
	public function Get($arg1);
	public function EOF();
}
interface OStream extends ISSKStream {
	public function Write($arg1, $arg2);
	public function Put($arg1, $arg2);
}
interface IOStream extends ISSKStream, IStream, OStream {}

class FileStream implements IOStream {
	private $fp = null;
	private $filepath = null;
	
	public function Open($filename, $mode) {
		$this->fp=@fopen($filename, $mode);
		$this->filepath=$filename;
		if(!$this->fp) {
			throw new SSKIOStreamException("Can't open file $filename.");
		}
	}
	public function Close() {
		if($this->fp) {
			if(!fclose($this->fp)) {
				throw new SSKIOStreamException("Can't close file.");
			}
			$this->hostname = null;
			$this->port = null;
		} else {
			throw new SSKIOStreamException('No file opened.');
		}
	}
	public function Read($length=1) {
		if($this->fp) {
			$read=fread($this->fp, $length);
			if(!$read) {
				throw new SSKIOStreamException("Can't read from file.");
			}
			return $read;
		} else {
			throw new SSKIOStreamException('No file opened.');
		}
	}
	public function Write($write, $length=null) {
		if($this->fp) {
			if(!$length) {
				if(!fwrite($this->fp, $write)) {
					throw new SSKIOStreamException("Can't write to file.");
				}
			} else {
				if(!fwrite($this->fp, $write, $length)) {
					throw new SSKIOStreamException("Can't write to file.");
				}
			}
		} else {
			throw new SSKIOStreamException('No file opened.');
		}
	}
	public function Get($length=null) {
		if($this->fp) {
			if(!$length) {
				$gets=fgets($this->fp);
			} else {
				$gets=fgets($this->fp, $length);
			}
			if(!$gets) {
				throw new SSKIOStreamException("Can't read from file.");
			}
			return $gets;
		} else {
			throw new SSKIOStreamException('No file opened.');
		}
	}
	public function Put($put, $length=null) {
		if($this->fp) {
			if(!$length) {
				if(!fputs($this->fp, $put)) {
					throw new SSKIOStreamException("Can't write to file.");
				}
			} else {
				if(!fputs($this->fp, $put, $length)) {
					throw new SSKIOStreamException("Can't write to file.");
				}
			}
		} else {
			throw new SSKIOStreamException('No file opened.');
		}
	}
	public function GetStream() {
		return $this->fp;
	}
	public function GetFSize() {
		filesize($this->filepath);
	}
	public function EOF() {
		return feof($this->fp);
	}
}
class SockStream extends FileStream implements IOStream {
	private $fp = null;
	private $hostname = null;
	private $port = null;
	
	public function Open($hostname, $port) {
		$this->fp=@fsockopen($hostname, $port, $errno, $errstr);
		if(!$this->fp) {
			throw new SSKIOStreamException("Can't open file at '$hostname:$port': '$errno $errstr'");
		}
	}
	public function Close() {
		if($this->fp) {
			if(!fclose($this->fp)) {
				throw new SSKIOStreamException("Can't close file.");
			}
			$this->hostname = null;
			$this->port = null;
		} else {
			throw new SSKIOStreamException('No file opened.');
		}
	}
	public function GetFSize() {
		return -1;
	}
}
?>